import {ref, watch} from 'vue'
import Layers from "@/lang/layers";
import Dictionary, {DictionaryItem} from "../../lang/dict/dictionary";

/**
 * 使用数据字典
 */
export interface UseDictionary {
    /** 数据字典配置，允许是数组或者数据字典ID */
    options?: DictionaryItem[] | string
    /** 字典查询参数，变化之后触发查询 */
    where?: Record<string, any>
    /** 异步获取字典数据的函数 */
    provider?: (options: string | Record<string, any> | DictionaryItem[]) => Promise<Dictionary>
}

/**
 * 默认的数据字典查询函数
 * @param options 数据字典配置
 * @constructor
 */
export const DEF_QUERY = (options: DictionaryItem[] | string): Promise<Dictionary> => {
    if (options == null) {
        // 返回一个空的数据字典
        return Promise.resolve(Dictionary.DEF);
    } else if (Array.isArray(options)) {
        // 将指定的数据列表，转换为数据字典
        return Promise.resolve(new Dictionary(options));
    } else if (typeof options === 'string') {
        // 使用数据字典的 key，从后台进行加载
        return Dictionary.query(options);
    } else {
        // 位置的数据格式
        throw 'Data-dictionary only accept array or string: ' + options;
    }
}

/**
 * 允许外部代码调整的一些配置
 *
 * 受影响组件：select/radio/checkbox/dictionary 相关的组件
 */
export const setting = {

    /**
     * 数据字典查询函数
     */
    provider: DEF_QUERY
}

/**
 * 使用数据字典
 *
 * 一个通用的数据字典查询，包含数据字典的查询，
 *
 * @param props - 组件入参
 * @param onchange - 数据字典变化事件
 */
export function useDictionary<T>(props: UseDictionary, onchange: (dict: Dictionary) => void = Layers.method()) {

    // 数据字典列表
    const opts: Ref<DictionaryItem[]> = ref<DictionaryItem>([]);

    // 数据加载状态
    const loading: Ref<boolean> = ref(false);

    // 数据字典查询函数
    const provider = props.provider || setting.provider;

    /**
     * 设值数据字典
     *
     * @param val 字典
     */
    const setOptions = (val): void => {
        provider(val).then(dic => {
            opts.value = dic.list;
            onchange(dic);
        });
    }

    /**
     * 查询远程数据字典
     */
    const reload = (params): void => {
        loading.value = true;
        provider(params).then(dic => {
            opts.value = dic.list;
            onchange(dic);
        }).finally(() => {
            loading.value = false;
        });
    }

    watch(() => props.options, setOptions);

    watch(() => props.where, reload);

    // 首次载入数据
    if (props.options != null) {
        // 下拉数据选项
        setOptions(props.options);
    } else if(props.provider != null){
        // 查询远程数据字典
        reload(props.where);
    }

    return {opts, loading}
}